
#include "Device.h"
#include "spdlog/fmt/bundled/format.h"
#include <vector>

// namespace fs = std::filesystem;

int main(int argc, char *argv[])
{
    auto console_sink = std::make_shared<spdlog::sinks::stdout_color_sink_mt>();
    auto logger = std::make_shared<spdlog::logger>("logger", spdlog::sinks_init_list { console_sink });

    logger->set_pattern("[%Y-%m-%d %H:%M:%S.%f] [%^%l%$] [%t] [%s:%#] %v");
    spdlog::set_default_logger(logger);
    logger->set_level(spdlog::level::info);

    bool enable_core = false;

    std::string root_path = "/opt/images";
    if (argc == 1)
    {
        return -1;
    }

    if (argc == 3)
    {
        root_path = argv[2];
    }

    if (argc == 4)
    {
        root_path = argv[2];
        enable_core = true;
    }

    auto config_file = argv[1];

    try
    {
        std::filesystem::create_directories(root_path);
    }
    catch (...)
    {
    }

    std::vector<std::shared_ptr<Device>> devices;
    int32_t core_idx = 0;

    if (std::filesystem::is_regular_file(config_file))
    {
        try
        {
            core_idx = std::stoi(argv[3]);

            nlohmann::json doc;
            std::ifstream json_file(config_file);
            json_file >> doc;
            json_file.close();

            std::cout << "rtsp: " << doc["rtsp_address"].get<std::string>() << std::endl;
            std::string rtsp_url = doc["rtsp_address"].get<std::string>();
            std::string device_id = doc["device_id"].get<std::string>();

            auto device = std::make_shared<Device>();
            device->Init(rtsp_url, device_id);
            device->SetOutDir(root_path);

            devices.push_back(device);

            auto size = devices.size();

            int idx = 0;
            for (auto &&device : devices)
            {
                idx++;
                device->Start();
            }
        }
        catch (const std::filesystem::filesystem_error &e)
        {
            std::cerr << "Filesystem error: " << e.what() << std::endl;
        }
        catch (const std::exception &e)
        {
            std::cerr << "Exception: " << e.what() << std::endl;
        }
    }
    else if (std::filesystem::is_directory(config_file))
    {
        try
        {
            std::vector<std::filesystem::path> vec_files;
            for (const auto &entry : std::filesystem::directory_iterator(argv[1]))
            {
                std::cout << entry.path() << std::endl;
                std::string filepath = entry.path().string();

                vec_files.push_back(filepath);
            }

            auto size = vec_files.size();

            int idx = 0;
            for (auto &&filepath : vec_files)
            {

                nlohmann::json doc;
                std::ifstream json_file(filepath);
                json_file >> doc;
                json_file.close();

                std::cout << "rtsp: " << doc["rtsp_address"].get<std::string>() << std::endl;
                std::string rtsp_url = doc["rtsp_address"].get<std::string>();
                std::string device_id = doc["device_id"].get<std::string>();

                auto device = std::make_shared<Device>();

                int32_t gpu_idx = (idx > size / 2) ? 1 : 0;
                int core_idx = -1;

                device->Init(rtsp_url, device_id, gpu_idx, core_idx);
                device->SetOutDir(root_path);

                devices.push_back(device);

                idx++;
                device->Start();
            }
        }
        catch (const std::filesystem::filesystem_error &e)
        {
            std::cerr << "Filesystem error: " << e.what() << std::endl;
        }
        catch (const std::exception &e)
        {
            std::cerr << "Exception: " << e.what() << std::endl;
        }
    }

    toolkit::Timer timer(
        10.0,
        []() {
            SPDLOG_INFO(FpsManager::GetInstance()->Dump());
            return true;
        },
        nullptr);

    toolkit::Timer timer2(
        10.0,
        [devices]() {
            std::stringstream ss;
            for (auto &&device : devices)
            {
                ss << device->DeviceID() << "\t" << device->ReconnectTimes() << "\n";
            }

            SPDLOG_INFO(ss.str());
            return true;
        },
        nullptr);

    getchar();

    for (auto &&device : devices)
    {
        device->Stop();
    }
}